package com.cookbook.animals;

import android.app.Activity;
import android.content.Intent;
import android.content.res.Configuration;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.speech.RecognizerIntent;
import android.view.View;
import android.widget.*;
import android.database.sqlite.*;
import android.graphics.*;
import android.content.pm.ActivityInfo;

import java.util.*;


public class animals extends Activity{
	// Define variable to hold request code for voice recognition
	private static final int VOICE_RECOGNITION_REQUEST_CODE = 4534;
	
	// Declare variable to hold db_helper
	DatabaseHelper db_helper;
	
	// Declare variable to hold db
	SQLiteDatabase db;
	
	// Declare variable to hold whether or not sound is playing and hold should be on
	boolean hold;
	
	// Declare variables to hold number of consecutive misses and whether the correct answer
		// has been given yet or not
	int misses;
	
	// Declare variable to hold id of current animal
	int id;
	
	// Declare variable to hold number of questions answered
	int answered;
	
	// Declare array to hold ids of animals chosen
	int animals[] = new int[10];
	
	// Declare variable to hold name of user
	String user;
	
	// Declare ArrayList<String> variable to hold names of animals
	ArrayList<String> names = new ArrayList<String>();
	
	// Declare TextView to hold title
	TextView title;
	
	/** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.solo_picture);

        // Instantiate new DatabaseHelper variable
        db_helper = new DatabaseHelper(this);
        
        // Check if savedInstanceState is non-null
        if(savedInstanceState != null){
        	// If so get info of last state
        	
        	// Get user from bundle
        	user = savedInstanceState.getString("user");
        	
        	// Get id from bundle
        	id = savedInstanceState.getInt("id");
        	
        	// Get animals array from bundle
        	animals = savedInstanceState.getIntArray("animals");
        	
        	// Get answered from bundle
        	answered = savedInstanceState.getInt("answered");
        	
        	Toast.makeText(getApplicationContext(), String.format("answered: %d", answered), Toast.LENGTH_SHORT).show();
        	
        	// Get misses from bundle
        	misses = savedInstanceState.getInt("misses");
        	
        	Toast.makeText(getApplicationContext(), String.format("misses: %d", misses), Toast.LENGTH_SHORT).show();
        }
        
        // Else there was no last state so generate new info
        else{
        	// Get user from calling activity
        	user = this.getIntent().getStringExtra("user");
            
        	// Generate 10 random animals from database and save id's to array
            animals = generateAnimals();
            
            // Initialize answered variable to 0
            answered = 0;
            
            // Initialize misses to 0
            misses = 0;
            
            // Initialize id to id of first animal
            id = animals[answered];
        }
        
        // Initialize hold to false
        hold = false;
        
        // Instantiate talk button
        Button talk = (Button) findViewById(R.id.talk);
        
        // Instantiate RelativeLayout
        RelativeLayout background = (RelativeLayout) findViewById(R.id.relativeLayout1);
        
        // Instantiate TextView to hold title
        title = (TextView) findViewById(R.id.title2);
        
		// Open database for reading and writing
		db = db_helper.getWritableDatabase();
		
		// Read color of this animal and save it to color
		int color = db_helper.getColor(db, id);
		
		// Close database
		db.close();

		// Check if color is 0
		if(color == 0){
			// If so then color is black so change color to RGB value for black
			color = 0xff000000;
		}
		
		// Else color is white
		else{
			// If so then change color to RGB value for white
			color = 0xffffffff;
		}
		
		// Set color of name to be color for given animal
		title.setTextColor(color);
		
		// Instantiate picture id to 0
		int picture_id = 0;
		
		// Check if current orientation is portrait
		if(this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT){
			// If so convert id of animal to id of its portrait picture
			picture_id = id2Picture1(id);
		}
		
		// Else current orientation is landscape
		else{
			// If so convert id of animal to id of its landscape picture
			picture_id = id2Picture2(id);
		}
        	
        // Load picture of animal into background of layout
        background.setBackgroundResource(picture_id);
        
        // Fill names array with a buffer spot and all of the animals names
        names.add("buffer");
        names.add("Cow");
        names.add("Pig");
        names.add("Dog");
        names.add("Horse");
        names.add("Sheep");
        names.add("Cat");
        names.add("Chicken");
        names.add("Squirrel");
        names.add("Duck");
        names.add("Frog");
        names.add("Turkey");
        names.add("Lion");
        names.add("Tiger");
        names.add("Bear");
        names.add("Monkey");
        names.add("Fish");
        names.add("Parrot");
        names.add("Dolphin");
        names.add("Eagle");
        names.add("Donkey");
        names.add("Wolf");
        names.add("Snake");
        names.add("Mouse");
        names.add("Elephant");
        names.add("Bee");
        names.add("Bat");
        names.add("Cricket");
        names.add("Goose");
        names.add("Rooster");
        names.add("Owl");
        
        // Start a listener for talk button
        talk.setOnClickListener(new View.OnClickListener() {
			// Override onClick function
			@Override
			public void onClick(View v) {
				// Make sure there isnt a hold
				if(!hold){
					// If not start speach to text
					start_speach2text();
				}
			}	
		});
    }	

    // Define start_speach2text function
    private void start_speach2text() {
		// Set hold to true
		hold = true;
		
    	// Start speech recognition activity
    	Intent start_recognition = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
    	start_recognition.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
    	start_recognition.putExtra(RecognizerIntent.EXTRA_PROMPT, "Say your answer now");
    	

		// Specify how many results you want to receive. The results will be sorted
			// where the first result is the one with higher confidence.
		start_recognition.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 3);

    	startActivityForResult(start_recognition, VOICE_RECOGNITION_REQUEST_CODE);
    }
    
    // Override onActivityResult function
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data){
    	if(requestCode == VOICE_RECOGNITION_REQUEST_CODE && resultCode == RESULT_OK){
    		// Fill array with results strings
    		ArrayList<String> results = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);

    		// Open database for reading and writing
    		db = db_helper.getWritableDatabase();
    		
    		// Check whether any of the 3 results matched and save that bool
    		boolean matched = (db_helper.match(db, id, results.get(0)) || 
    			db_helper.match(db, id, results.get(1)) || db_helper.match(db, id, results.get(2)));
    		
    		// Close the database
    		db.close();
    		
    		// If there was a match
    		if(matched){
    			// If so convert id to id of correct message
    			int correct_id = id2Correct(id);

    			// Change text of title to be this animals name
    			title.setText(names.get(id));
    			
    			// Instantiate new media player
    			MediaPlayer mp1 = MediaPlayer.create(this, correct_id);

    			// Play correct message
    			mp1.start();

    			// Set listener to wait for on completion of mp1
    			mp1.setOnCompletionListener(new MediaPlayer.OnCompletionListener(){
    				// Override on completion
    				@Override
    				public void onCompletion(MediaPlayer mp){
    					// Release mp1
    					mp.release();

    					// Convert id of animal to id of sound
    					int sound_id = id2Sound(id);

    					// Prepare sound of animal
    					MediaPlayer mp2 = MediaPlayer.create(getApplicationContext(), sound_id);

    					// Play sound of animal
    					mp2.start();

    					// Open database for reading and writing
    					db = db_helper.getWritableDatabase();

    					// Read numbers for this animal from database
    					Long frequency = db_helper.getFrequency(db, user, id);

    					// Read stats for from database
    					ArrayList<Long> stats = db_helper.getStats(db, user);

    					// Update total and correct in stats table
    					db_helper.updateCorrect(db, user, stats.get(0).intValue() + 1);
    					db_helper.updateTotal(db, user, stats.get(1).intValue() + 1);

    					// Check if misses is 0
    					if(misses == 0){
    						// If so check if frequency is greater than 1
    						if(frequency.intValue() > 1){
    							// If so then decrease frequency for this animal in the database
    							db_helper.updateFrequency(db, user, id, frequency.intValue() - 1);
    						}
    					}

    					// Close database
    					db.close();

    					// Reset misses to 0
    					misses = 0;

    					// Increase answered
    					answered++;

    					// Set onCompletionListener for mp2
    					mp2.setOnCompletionListener(new MediaPlayer.OnCompletionListener(){
    						// Override onCompletion function
    						@Override
    						public void onCompletion(MediaPlayer mp){
    							// Release mp2
    							mp.release();

    							// Check if answered is 10
    							if(answered == 10){
    								// If so then close this activity
    								finish();
    							}

    							// Else continue
    							else{
    								// Set text of title back to normal
    								title.setText(R.string.instruction);
    								
    								// Set id to be id of next animal
    								id = animals[answered];

    								// Instantiate RelativeLayout
    								RelativeLayout background = (RelativeLayout) findViewById(R.id.relativeLayout1);

    								// Instantiate TextView to hold title
    								TextView title = (TextView) findViewById(R.id.title2);

    								// Open database for reading and writing
    								db = db_helper.getWritableDatabase();

    								// Read color of this animal and save it to color
    								int color = db_helper.getColor(db, id);

    								// Close database
    								db.close();

    								// Check if color is 0
    								if(color == 0){
    									// If so then color is black so change color to RGB value for black
    									color = 0xff000000;
    								}

    								// Else color is white
    								else{
    									// If so then change color to RGB value for white
    									color = 0xffffffff;
    								}

    								// Set color of name to be color for given animal
    								title.setTextColor(color);

    								// Instantiate picture id to 0
    								int picture_id = 0;

    								// Check if current orientation is portrait
    								if(animals.this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT){
    									// If so convert id of animal to id of its portrait picture
    									picture_id = id2Picture1(id);
    								}

    								// Else current orientation is landscape
    								else{
    									// If so convert id of animal to id of its landscape picture
    									picture_id = id2Picture2(id);
    								}

    								// Load picture of animal into background of layout
    								background.setBackgroundResource(picture_id);
    								
        							// Set hold back to false
        							hold = false;
    							}
    						}
    					});
    				}
    			});
    		}

    		// Else see if misses is less than 2
    		else if(misses < 2){
    			// Instantiate media player with try again message
    			MediaPlayer mp = MediaPlayer.create(this, R.raw.try_again);

    			// Play mp
    			mp.start();

    			// Increase misses
    			misses++;

    			// Setup onCompletionListener for mp
    			mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
    				// Override onCompletion function
    				@Override
    				public void onCompletion(MediaPlayer mp) {
    					// Release mp
    					mp.release();
    					
    					// Set hold back to false
    					hold = false;
    				}
    			});
    		}

    		// Else skip this animal
    		else{
    			// Get id of missed message for this animal
    			int missed_id = id2Missed(id);

    			// Instantiate a media player with this id
    			MediaPlayer mp = MediaPlayer.create(this, missed_id);

    			// Play mp
    			mp.start();

    			// Increase misses
    			misses++;

    			// Open database for reading and writing
    			db = db_helper.getWritableDatabase();

    			// Read frequency for this animal from database
    			Long frequency = db_helper.getFrequency(db, user, id);

    			// Read stats from database
    			ArrayList<Long> stats = db_helper.getStats(db, user);

    			// Increase frequency for this animal in the database
    			db_helper.updateFrequency(db, user, id, frequency.intValue() + 1);

    			// Update total field in stats table
    			db_helper.updateTotal(db, user, stats.get(1).intValue() + 1);

    			// Reset misses to 0
    			misses = 0;

    			// Increase answered
    			answered++;

    			// Close database
    			db.close();

    			// Setup onCompletionListener for mp
    			mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
    				// Override onCompletion function
    				@Override
    				public void onCompletion(MediaPlayer mp) {
    					// Release mp
    					mp.release();

    					// Check if answered is 10
    					if(answered == 10){
    						// If so then close this activity
    						finish();
    					}

    					// Else continue
    					else{
    						// Set id to be id of next animal
    						id = animals[answered];

    						// Instantiate RelativeLayout
    						RelativeLayout background = (RelativeLayout) findViewById(R.id.relativeLayout1);

    						// Instantiate TextView to hold title
    						TextView title = (TextView) findViewById(R.id.title2);

    						// Open database for reading and writing
    						db = db_helper.getWritableDatabase();

    						// Read color of this animal and save it to color
    						int color = db_helper.getColor(db, id);

    						// Close database
    						db.close();

    						// Check if color is 0
    						if(color == 0){
    							// If so then color is black so change color to RGB value for black
    							color = 0xff000000;
    						}

    						// Else color is white
    						else{
    							// If so then change color to RGB value for white
    							color = 0xffffffff;
    						}

    						// Set color of name to be color for given animal
    						title.setTextColor(color);

    						// Instantiate picture id to 0
    						int picture_id = 0;

    						// Check if current orientation is portrait
    						if(animals.this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT){
    							// If so convert id of animal to id of its portrait picture
    							picture_id = id2Picture1(id);
    						}

    						// Else current orientation is landscape
    						else{
    							// If so convert id of animal to id of its landscape picture
    							picture_id = id2Picture2(id);
    						}

    						// Load picture of animal into background of layout
    						background.setBackgroundResource(picture_id);

        					// Set hold back to false
        					hold = false;
    					}
    				}
    			});
    		}
    	}
    	
    	//super.onActivityResult(requestCode, resultCode, data);
    }
    
    // Override onSavedInstanceState function
    @Override
    public void onSaveInstanceState(Bundle outState){
    	// Call super function
    	super.onSaveInstanceState(outState);
    	
    	// Put user into outState bundle
    	outState.putString("user", user);
    	
    	// Put id into outState bundle
    	outState.putInt("id", id);
    	
    	// Put animals array into outState bundle
    	outState.putIntArray("animals", animals);
    	
    	// Put answered into outState bundle
    	outState.putInt("answered", answered);
    	
    	// Put misses into outState bundle
    	outState.putInt("misses", misses);
    }
    
    // Define generateAnimals function
    private int[] generateAnimals(){
    	// Create Long to hold results of database querries
    	Long results;
    	
    	// Create array to hold frequency of every animal in the database
    	ArrayList<Long> frequencies = new ArrayList<Long>();
    	
    	// Create array to hold id's of animals chosen and initialize values to -1
    	int ids[] = new int[10];
    	for(int i = 0; i < 10; i++){
    		ids[i] = -1;
    	}
    	
    	// Create variable to hold sum of all frequencies
    	int sum = 0;
    	
    	// Open database for reading and writing
    	db = db_helper.getWritableDatabase();
    	
    	// Fill frequencies with a query of database for every animal entry and sum them all
    	for(int i = 1; i <= DatabaseHelper.DB_SIZE; i++){
    		results = db_helper.getFrequency(db, user, i);
    		frequencies.add(results);
    		sum += results.intValue();
    	}
    	
    	// Close database
    	db.close();
    	
    	// Prepare a second array to hold id's of animals in database
    		// each animal gets as many spots as its frequency
    	if(sum > 0){
    		int chances[] = new int[sum];
    		int counter = 0;
    		for(int i = 0; i < DatabaseHelper.DB_SIZE; i++){
    			// Get frequency of current animal
    			int frequency = frequencies.get(i).intValue();
    		
    			// Add as many entries into chance array is animal has frequency
    			for(int j = 0; j < frequency; j++){
    				chances[counter++] = i+1;
    			}
    		}
    	
    		// Instantiate random number generator
    		Random randomGenerator = new Random();
    	
    		// Repeat selection method 10 times to pick 10 animals
    		for(int i = 0; i < 10; i++){
    			// Generate a random number between 0 and sum-1
    			int random_num = randomGenerator.nextInt(sum);
    		
    			// Get the id held in that entry in chances array
    			int choice = chances[random_num];
    		
    			// Make sure choice isn't already in animals
    			for(int j = 0; j < 10; j++){
    				if(choice == ids[j]){
    					// If it is a repeat then set choice to -1 and break for loop 
    					choice = -1;
    					break;
    				}
    			}
    		
    			// Check if choice is -1
    			if(choice == -1){
    				// If so random id chosen was a repeat so decrement i and repeat this
    					// iteration of selection method
    				i--;
    			}
    		
    			// Else assign id value in choice to current position in animals
    			else{
    				ids[i] = choice;
    			}
    		}
    	}
    	// Return animals
    	return ids;
    }
    
    // Make function to convert an animals id in the database to the id of its portrait picture
    int id2Picture1(int id){
    	return id + 0x7f020000 - 1;
    }
    
    // Make function to convert an animals id in the database to the id of its landscape picture
    int id2Picture2(int id){
    	return id + 0x7f020000 - 1 + DatabaseHelper.DB_SIZE;
    }
    
    // Make function to convert an animals id in the database to the id of its sound
    int id2Sound(int id){
    	return id + 0x7f040000 - 1;
    }
    
    // Make function to convert an animals id in the database to the id of its correct message
    int id2Correct(int id){
    	return id + 0x7f040000 - 1 + (2*DatabaseHelper.DB_SIZE); 
    }
    
    // Make function to convert an animals id in the database to the id of its missed message
    int id2Missed(int id){
    	return id + 0x7f040000 - 1 + (3*DatabaseHelper.DB_SIZE);
    }
}